#include "util/pipsutil.h"
#include "core/account.h"
#include "normalorder.h"

double NormalOrder::getOrderCurrPrice() const
{
    return m_currPrice;
}

double NormalOrder::getOrderClosePrice() const
{
    return 0;
}

time_t NormalOrder::getOrderCloseTime() const
{
    return 0;
}

void NormalOrder::setOrderCurrPrice(time_t time, double price)
{
    if (m_currTime > time) {
       return;
    }
    m_currTime = time;
    m_currPrice = price;
    if (m_currPrice > m_highPrice) {
        m_highPrice = m_currPrice;
    }
    if (m_currPrice < m_lowPrice) {
        m_lowPrice = m_currPrice;
    }
    if (m_isTrailStop) {
        if (m_type == ORDERBUY) {
            if (price - m_trailStop > m_stopLoss) {
                m_stopLoss = price - m_trailStop;
            }
        }
        else if (m_type == ORDERSELL) {
            if (price + m_trailStop < m_stopLoss) {
                m_stopLoss = price + m_trailStop;
            }
        }
    }
}

bool NormalOrder::close()
{
    Account *account = Account::inst();
    double balance = account->getAccountBalance();
    balance += this->getOrderNetProfit();
    account->setBalance(this->m_id, balance);
    double fee = account->getAccountFee();
    fee += this->getOrderPoint();
    account->setFee(fee);
    m_closeTime = m_currTime;
    m_closePrice = m_currPrice;
    return true;
}

double NormalOrder::getOrderProfit() const
{
    double profit = 0;
    if (m_type == ORDERBUY) {
        profit = m_lots * (m_currPrice - m_openPrice) * 10 / UTIL::getPips(m_symbol);
    }
    else if (m_type == ORDERSELL) {
        profit = -m_lots * (m_currPrice - m_openPrice) * 10 / UTIL::getPips(m_symbol);
    }
    return profit;
}

double NormalOrder::getOrderNetProfit() const
{
    double netProfit = 0;
    if (m_type == ORDERBUY || m_type == ORDERSELL) {
        netProfit = getOrderProfit() - getOrderPoint();
    }
    return netProfit;
}

double NormalOrder::getOrderPoint() const
{
    return m_lots * m_fee * 10 / UTIL::getPips(m_symbol);
}

bool NormalOrder::hitStopLoss() const
{
    if (m_stopLoss == 0.0) {
        return false;
    }
    if (m_type == ORDERBUY) {
        if (m_currPrice <= m_stopLoss) {
            return true;
        }
    }
    else if (m_type == ORDERSELL) {
        if (m_currPrice >= m_stopLoss) {
            return true;
        }
    }
    return false;
}

bool NormalOrder::hitTakeProfit() const
{
    if (m_takeProfit == 0.0) {
        return false;
    }
    if (m_type == ORDERBUY) {
        if (m_currPrice >= m_stopLoss) {
            return true;
        }
    }
    else if (m_type == ORDERSELL) {
        if (m_currPrice <= m_stopLoss) {
            return true;
        }
    }
    return false;
}

bool NormalOrder::setTrailStop(bool isTrailStop, double trailStop)
{
    if (!isTrailStop) {
        m_isTrailStop = false;
        return true;
    }
    if (trailStop > 0) {
        m_isTrailStop = isTrailStop;
        m_trailStop = trailStop * UTIL::getPips(m_symbol);
    }
    else {
        printf("Error: NormalOrder::setTrailStop(bool, double)");
    }
    return true;
}

bool NormalOrder::setStopLoss(double price)
{
    if (price == 0.0) {
        m_stopLoss = 0.0;
        return true;
    }
    if (m_type == ORDERBUY) {
        if (price >= m_currPrice || price < 0)
            return false;
    }
    else if (m_type == ORDERSELL) {
        if (price <= m_currPrice)
            return false;
    }
    m_stopLoss = price;
    return true;
}

bool NormalOrder::setTakeProfit(double price)
{
    if (price == 0.0) {
        m_takeProfit = 0.0;
        return true;
    }
    if (m_type == ORDERBUY) {
        if (price <= m_currPrice)
            return false;
    }
    else if (m_type == ORDERSELL) {
        if (price >= m_currPrice || price < 0)
            return false;
    }
    m_takeProfit = price;
    return true;
}